/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.sonar.util.ui.props;

import bgu.sonar.util.meta.Meta;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.PropertySupport;
import org.openide.nodes.Sheet;

/**
 *
 * @author bennyl
 */
public class PropertyBeanNode extends AbstractNode {

    Object target;

    public PropertyBeanNode(Object obj) {
        super(Children.LEAF);
        this.target = obj;
    }

    @Override
    protected Sheet createSheet() {
        Sheet sheet = Sheet.createDefault();
        if (target == null) {
            return sheet;
        }

        Map<String, Sheet.Set> sets = new HashMap<>();
        createProperties(sets);
        for (Sheet.Set s : sets.values()) {
            sheet.put(s);
        }

        return sheet;
    }

    private void createProperties(Map<String, Sheet.Set> sets) throws SecurityException {
        Map<String, Meta.Metadata> fields = Meta.Support.extractFieldMap(target);

        for (final Meta.Metadata f : fields.values()) {
            PropertySupport.ReadWrite prop = new PropertySupport.ReadWrite(f.getVisualName(), f.getType(), f.getVisualName(), f.getDescription()) {
                @Override
                public Object getValue() throws IllegalAccessException, InvocationTargetException {
                    return f.getField().get(target);
                }

                @Override
                public void setValue(Object val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
                    f.getField().set(target, val);
                }
            };

            String propSet = "Properties";
            Sheet.Set set = sets.get(propSet);
            if (set == null) {
                set = Sheet.createPropertiesSet();
                set.setDisplayName(propSet);
                set.setName(propSet);
                sets.put(propSet, set);
            }

            // add the property to the matching set
            set.put(prop);
        }
    }
}
